package com.nacrtstudio.webgiftshop.facade.impl;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.Session;

import com.nacrtstudio.webgiftshop.facade.Controller;
import com.nacrtstudio.webgiftshop.model.service.Manager;
import com.nacrtstudio.webgiftshop.model.shop.Address;
import com.nacrtstudio.webgiftshop.model.shop.Cart;
import com.nacrtstudio.webgiftshop.model.shop.CartItem;
import com.nacrtstudio.webgiftshop.model.shop.Category;
import com.nacrtstudio.webgiftshop.model.shop.Comment;
import com.nacrtstudio.webgiftshop.model.shop.Gift;
import com.nacrtstudio.webgiftshop.model.shop.Order;
import com.nacrtstudio.webgiftshop.model.shop.PackedGift;
import com.nacrtstudio.webgiftshop.model.shop.User;
import com.nacrtstudio.webgiftshop.model.shop.beans.AddressBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.CartBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.CartItemBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.CategoryBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.GiftBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.OrderBean;
import com.nacrtstudio.webgiftshop.model.shop.beans.PackedGiftBean;
import com.nacrtstudio.webgiftshop.model.website.QandA;
import com.nacrtstudio.webgiftshop.model.website.beans.QandABean;
import com.nacrtstudio.webgiftshop.pages.ShoppingCart;
import com.nacrtstudio.webgiftshop.util.shop.Country;
import com.nacrtstudio.webgiftshop.util.shop.OrderStatus;
import com.nacrtstudio.webgiftshop.util.shop.SerbiaTowns;

public class ControllerImpl implements Controller{
	private Manager<Address> addressManager;
	private Manager<Cart> cartManager;
	private Manager<CartItem> cartItemManager;
	private Manager<Category> categoryManager;
	private Manager<Comment> commentManager;
	private Manager<Gift> giftManager;
	private Manager<Order> orderManager;
	private Manager<PackedGift> packedGiftManager;
	private Manager<User> userManager;
	private Manager<QandA> qandAManager;
	public static final String AUTH_TOKEN = "authToken";
	private static Request request;
	private User user;
	
	
	public Manager<Address> getAddressManager() {
		return addressManager;
	}
	public void setAddressManager(Manager<Address> addressManager) {
		this.addressManager = addressManager;
	}
	public Manager<Cart> getCartManager() {
		return cartManager;
	}
	public void setCartManager(Manager<Cart> cartManager) {
		this.cartManager = cartManager;
	}
	public Manager<Category> getCategoryManager() {
		return categoryManager;
	}
	public void setCategoryManager(Manager<Category> categoryManager) {
		this.categoryManager = categoryManager;
	}
	public Manager<Comment> getCommentManager() {
		return commentManager;
	}
	public void setCommentManager(Manager<Comment> commentManager) {
		this.commentManager = commentManager;
	}
	public Manager<Gift> getGiftManager() {
		return giftManager;
	}
	public void setGiftManager(Manager<Gift> giftManager) {
		this.giftManager = giftManager;
	}
	public Manager<Order> getOrderManager() {
		return orderManager;
	}
	public void setOrderManager(Manager<Order> orderManager) {
		this.orderManager = orderManager;
	}
	public Manager<PackedGift> getPackedGiftManager() {
		return packedGiftManager;
	}
	public void setPackedGiftManager(Manager<PackedGift> packedGiftManager) {
		this.packedGiftManager = packedGiftManager;
	}
	public Manager<User> getUserManager() {
		return userManager;
	}
	public void setUserManager(Manager<User> userManager) {
		this.userManager = userManager;
	}
	public Manager<CartItem> getCartItemManager() {
		return cartItemManager;
	}
	public void setCartItemManager(Manager<CartItem> cartItemManager) {
		this.cartItemManager = cartItemManager;
	}
	
	
	
	public Manager<QandA> getQandAManager() {
		return qandAManager;
	}
	public void setQandAManager(Manager<QandA> qandAManager) {
		this.qandAManager = qandAManager;
	}
	public Request getRequest() {
		return request;
	}
	public void setRequest(Request request) {
		ControllerImpl.request = request;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	
//	User commands
	public List<User> getAllUsers() {
		return (List<User>) getUserManager().getAll(User.class);
	}
	public User getUserByEmail(String email) {
		return getUserManager().getByPropertyValue(User.class, "eMail", email);
	}
	public User checkUser(String username, String password) {
		User user = getUserByUsername(username);
		if (user!=null && user.getPassword().equals(password)) {
			return user;
		}
		return null;
	}
	public User getUserByUsername(String username) {
		return getUserManager().getByPropertyValue(User.class, "username", username);
	}
	public boolean login(String username, String password) {
		setUser(checkUser(username, password));
		if (getUserByUsername(username)!=null) {
			getRequest().getSession(true).setAttribute(AUTH_TOKEN, getUser());
			return true;
		}
		return false;
	}
	public boolean isLoggedIn() {
		Session session = getRequest().getSession(false);
		if (session != null) {
			return session.getAttribute(AUTH_TOKEN) != null;
		}
		return false;
	}
	public boolean getLoggedSignal() {
		if (isLoggedIn()) {
			return true;
		}
		return false;
	}
	public User getLoggedUser() {
		try {
			if (isLoggedIn()) {
				setUser((User) getRequest().getSession(true).getAttribute(AUTH_TOKEN));
			} else {
				throw new IllegalStateException("\n\n\nKupac nije ulogovan\n\n\n");
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return getUser();
	}
	
	public boolean logout() {
		Session session = getRequest().getSession(false);
		if(session!=null){
			session.setAttribute(AUTH_TOKEN, null);
			session.invalidate();
			return true;
		}
		return false;
	}
	public boolean login(User principal) {
		setUser(principal);
		if (getUser()!=null) {
			getRequest().getSession(true).setAttribute(AUTH_TOKEN, getUser());
			return true;
		}
		return false;
	}
	public String signUpUser(User user, String rePassword) {
		if (user.getPassword().equals(rePassword)) {
			if (getUserByUsername(user.getUsername())==null) {
				user.setCart(new CartBean());
				getUserManager().setObject(user);
				getUserManager().create();
				return "Uspešno ste se registrovali! :)";
			} else {
				return "Došlo je do greške. Molimo Vas pokušajte ponovo! :(";
			}
		} else {
			return "Vaše šifre se ne podudaraju!";
		}
	}
	public void updateUser(User user){
		getUserManager().update(user);
	}
	
	public void deleteShoopingCardFromLoggedUser() {
		Cart cart = new CartBean();
		cart.setCartItems(new HashSet<CartItem>());
		getLoggedUser().setCart(cart);
		getUserManager().update(getLoggedUser());
		
	}
	public void deleteItemFromShoppingCart(CartItem cartItem) {
		try {
			getLoggedUser().getCart().getCartItems().remove(cartItem);
		} catch (Exception e) {
		}
	}
/*
 * 
 * 
 * 
 * (non-Javadoc)
 * @see com.nacrtstudio.webgiftshop.facade.Controller#addGiftToCart(java.lang.Long)
 */
	public Object addGiftToCart(Long id){
		try {
			if (getLoggedSignal()) {
				if (getSignalIfGiftExistInCart(id)) {
					addMore(id);
					return ShoppingCart.class;
				} else {
					CartItem cartItem = new CartItemBean();
					Gift gift = findGift(id);
					cartItem.setCartItemId((long) (getCartItemManager().getAll(CartItem.class).size()+1));
            		cartItem.setGift(gift);
					cartItem.setQty(1);
					cartItem.setCart(getLoggedUser().getCart());
					getCartItemManager().update(cartItem);
					if (getLoggedUser().getCart()==null) {
						getLoggedUser().setCart(new CartBean());
					}
	        		if (getLoggedUser().getCart().getCartItems()==null) {
	        			getLoggedUser().getCart().setCartItems(new HashSet<CartItem>());
					}
	        		getLoggedUser().getCart().getCartItems().add(cartItem);
	        		getUserManager().update(getLoggedUser());
	    			return ShoppingCart.class;
				}
    		} 
		} catch (Exception e) {
			System.out.println("\n\n\n\n______________ "+e);
		}
		return null;
	}
	
	
	private boolean getSignalIfGiftExistInCart(Long id) {
		for (CartItem cartItem : getLoggedUser().getCart().getCartItems()) {
			if (cartItem.getGift().equals(findGift(id))) {
				return true;
			}
		}
		return false;
	}
	
	public void addMore(Long id) {
		for (CartItem cartItem : getLoggedUser().getCart().getCartItems()) {
			if (cartItem.getGift().equals(findGift(id))) {
				cartItem.setQty(cartItem.getQty()+1);
				getCartItemManager().update(cartItem);
			}
		}
	}
	//	Categorizing
	public void createCategory(Category category) {
		getCategoryManager().setObject(category);
		getCategoryManager().create();
	}
	
	public void createCategory(String categoryName, String description){
		Category newCategory = new CategoryBean();
		if (getAllCategories().size()!=0) {
			newCategory.setCategoryID((long) (getAllCategories().get((getAllCategories().size()-1)).getCategoryID()+1));
		} else  {
			newCategory.setCategoryID(1L);
		}
		newCategory.setCategoryName(categoryName);
		newCategory.setDescription(description);
		getCategoryManager().setObject(newCategory);
		getCategoryManager().create();
	}
	
	public List<Category> getAllCategories() {
		return (List<Category>) getCategoryManager().getAll(Category.class);
	}
	public boolean deleteCategory(Category deleteCategory) {
		try {
			getCategoryManager().setObject(deleteCategory);
			getCategoryManager().delete();
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	public void deleteCategory(Long id) {
		Category c= getCategory(id);
		deleteCategory(c);
	}
	public Category getCategory(Long id) {
		return getCategoryManager().getByPropertyID(Category.class, "categoryID", id);
	}
	public void updateCategory(Category editCategory) {
		getCategoryManager().update(editCategory);
	}
	public Category getCategoryByName(String categoryName) {
		return getCategoryManager().getByPropertyValue(Category.class, "categoryName", categoryName);
	}
	
	
//	Gifts
	public void createGift(Gift gift) {
		getGiftManager().setObject(gift);
		getGiftManager().create();
	}
	
	public void createGift(String imgPath, String giftName, String description, String altText, String categoryName, String price, List<String> imgList, boolean specialContent) {
		Gift newGift = new GiftBean();
		newGift.setImgPath(imgPath);
		if (getAllGifts().size()!=0) {
			newGift.setGiftId((getAllGifts().get(getAllGifts().size()-1).getGiftId()+1));
		} else {
			newGift.setGiftId(1L);
		}
		newGift.setGiftName(giftName);
		newGift.setDescription(description);
		newGift.setAltText(altText);
		newGift.setCategory(getCategoryByName(categoryName));
		try {
			newGift.setPrice(Double.parseDouble(price));
		} catch (Exception e) {
			System.out.println("nije uspelo\n\n\n\n");
		}
		newGift.setImgsOfGiftContent(imgList);
		newGift.setSpecialContent(specialContent);
		getGiftManager().setObject(newGift);
		getGiftManager().create();
	}
	
	
	public List<Gift> getAllGifts() {
		return getGiftManager().getAll(Gift.class);
	}
	public List<Gift> getSortedGifts() {
		return getGiftManager().getAllSortedByProperty(Gift.class, "price");
	}
	public Gift findGift(Long id) {
		return getGiftManager().getByPropertyID(Gift.class, "giftId", id);
	}
	public boolean deleteGift(Gift gift) {
		try {
			getGiftManager().setObject(gift);
			getGiftManager().delete();
		} catch (Exception e) {
			return false;
		}
		return false;
	}
	public void updateGift(Gift editGift) {
		getGiftManager().update(editGift);
	}
	public List<Gift> getAllGiftsFromCategory(Category category) {
		List<Gift> gifts = new LinkedList<Gift>();
		for (Gift gift : getSortedGifts()) {
			if (gift.getCategory().equals(category)) {
				gifts.add(gift);
			}
		}
		return gifts;
	}
	public List<Gift> getMostWantedGifts() {
		return getGiftManager().getAllByMaxValue(Gift.class, "howManyTimesIsChosen");
	}
	
	
	
//	Packaging
	public Object packGifts() {
		try {
			Order order = new OrderBean();
			Set<PackedGift> packedGifts = new HashSet<PackedGift>();
			order.setUser(getLoggedUser());
			order.setPackedGifts(packedGifts);
			if (getAllOrders().size()!=0) {
				order.setOrderId(getAllOrders().get(getAllOrders().size()-1).getOrderId()+1);
			} else {
				order.setOrderId(1L);
			}
			
			for (CartItem cartItem : getLoggedUser().getCart().getCartItems()) {
				for (int i = 0; i < cartItem.getQty(); i++) {
					PackedGift packedGift = new PackedGiftBean();
					order.getPackedGifts().add(packedGift);
					if (getAllPackedGifts().size()!=0) {
						packedGift.setChosenGiftId(getAllPackedGifts().get(getAllPackedGifts().size()-1).getChosenGiftId()+1);
					} else {
						packedGift.setChosenGiftId(1L);
					}
					Address address = new AddressBean();
					if (getAllAddress().size()!=0) {
						packedGift.setChosenGiftId(getAllPackedGifts().get(getAllPackedGifts().size()-1).getChosenGiftId()+1);
						address.setAddressId(getAllAddress().get(getAllAddress().size()-1).getAddressId()+1);
					} else {
						address.setAddressId(1L);
					}
					address.setCountry(Country.Serbia_and_Montenegro);
					address.setTown(SerbiaTowns.Beograd);
					address.setStreet("Kneza Višeslava");
					packedGift.setAddress(address);
					packedGift.setMessageText("Poruka");
					packedGift.setGift(cartItem.getGift());
					packedGift.setOrder(order);
					createPackedGift(packedGift);
				}
			}
			return order;
		} catch (Exception e) {
			System.out.println("---!!!---\n"+e);
		}
		return null;
	}
	public Object packGiftsFromCart() {
		try {
			Set<PackedGift> packedGifts = new HashSet<PackedGift>();
			for (CartItem cartItem : getLoggedUser().getCart().getCartItems()) {
				for (int i = 0; i < cartItem.getQty(); i++) {
					PackedGift packedGift = new PackedGiftBean();
					if (getAllPackedGifts().size()!=0) {
						packedGift.setChosenGiftId(getAllPackedGifts().get(getAllPackedGifts().size()-1).getChosenGiftId()+1);
					} else {
						packedGift.setChosenGiftId(1L);
					}
					Address address = new AddressBean();
					address.setCountry(Country.Serbia_and_Montenegro);
					address.setTown(SerbiaTowns.Beograd);
					address.setStreet("");
					packedGift.setAddress(address);
					packedGift.setMessageText("");
					packedGift.setNameOfReceiver("");
					packedGift.setNameOfSender(getLoggedUser().getFirstName()+" "+getLoggedUser().getLastName());
					packedGift.setShippingPrice(address.getTown().getShippingPrice());
					packedGift.setGift(cartItem.getGift());
					packedGifts.add(packedGift);
				}
			}
			return packedGifts;
		} catch (Exception e) {
			System.out.println("---!!!---\n"+e);
		}
		return null;
	}
	public List<Address> getAllAddress(){
		return getAddressManager().getAll(Address.class);
	}
	public List<PackedGift> getAllPackedGifts() {
		return getPackedGiftManager().getAll(PackedGift.class);
	}
	public void createPackedGift(PackedGift packedGift){
		getPackedGiftManager().setObject(packedGift);
		getPackedGiftManager().create();
	}
	public PackedGift findPackedGift(Long id) {
		return getPackedGiftManager().getByPropertyID(PackedGift.class, "chosenGiftId", id);
	}
	
//	Ordering
	public void createOrder(Order order) {
		getOrderManager().setObject(order);
		getOrderManager().create();
	}
	public List<Order> getAllOrders() {
		return getOrderManager().getAll(Order.class);
	}
	public Order getOrderStatus(Long orderId){
		for (Order order : getAllOrders()) {
			if (order.getOrderId().equals(orderId)) {
				return order;
			}
		}
		return null;
	}
	
	public Order findOrder(Long id) {
		return getOrderManager().getByPropertyID(Order.class, "orderId", id);
	}
	
	
//	Statusing
	public OrderStatus getOrderStatus(Order order) {
		return order.getOrderStatus();
	}
	public void setOrderStatus(Order order, OrderStatus status) {
		order.setOrderStatus(status);
		getOrderManager().update(order);
	}
	
//  Items
	public void createCartItem(CartItem cartItem){
		getCartItemManager().setObject(cartItem);
		getCartItemManager().create();
	}
	public CartItem findCartItem(Long id) {
		return getCartItemManager().getByPropertyID(CartItem.class, "cartItemId", id);
	}
	
//	QandA
	public void saveQandA(String question, String answer){
		QandA qandA = new QandABean();
		qandA.setQuestion(question);
		qandA.setAnswer(answer);
		getQandAManager().update(qandA);
	}
	
	public List<QandA> getQandAList(){
		return getQandAManager().getAll(QandA.class);
	}

}